package com.gpscookie.vocabularystory;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.text.DateFormatter;

public class Main {
	
	protected static int LIMIT = 60;
	protected static boolean isTranslate = true;
	protected static boolean isSave = false;
	protected static boolean ruleOutBasic = true;
	protected static boolean showContext = false;
	protected static boolean showRuleOut = false;
	
	protected static String[] BASICLIST = {"data/basic.txt", "data/basicbooktwo.txt"};
	protected static String subtitle = "data/bookthree.txt";	
	protected static String BOOKTITLE = "大学精读第三册";
	protected static String BOOKID = "ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYv4UCDA";
	private static String BOOKURL = "http://www.gpscookie.cn/upload/"+BOOKID+".json";	
	private static String outjson = "output/"+BOOKID+".json";
	private static String JSONHEAD = "{\"error\":0, \"msg\":\"\", \"title\":\"%s\", \"url\":\"%s\", \"key\":\"%s\", \"total\":%d, \"result\":[";
	// sample: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYm6kCDA
	// shawshank: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sY2JsBDA	
	// basic: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sY_aUBDA
	// usa constitution:ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYlLgBDA
	// genesis: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sY77gBDA
	// friendss01e01: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYsYICDA
	// bigbangs04e15: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYp6ECDA
	// lovestory: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYr5QBDA
	// heyjude: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sY3ooCDA
	// inception: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYuZICDA
	// bookone: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sY5IMCDA
	// booktwo: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sY5psCDA
	// bookthree: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYv4UCDA
	// bookfour: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYyY0CDA
	// bookfive: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sY98MCDA
	// booksix: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sY1qUCDA
	// houses07e12: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sY270CDA
	// gossipgirls04e15: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYzqYCDA
	// tofel: ag92b2NhYnVsYXJ5c3RvcnlyDAsSBEJvb2sYwZ8CDA	
	private static int padding = 70;

	
	private static String getEntryUrl(String entry) throws UnsupportedEncodingException {
	    // data += "&" + URLEncoder.encode("url", "UTF-8") + "=" + URLEncoder.encode("http://en.wiktionary.org/wiki/"+entry, "UTF-8");		
		return "http://dict.youdao.com/m/search?keyfrom=dict.mindex&vendor=%24vendor&q="+entry;
	}

	/**
	 * @param args
	 */
	public static void work(String[] args) {
		BOOKURL = "http://www.gpscookie.cn/upload/"+BOOKID+".json";	
		outjson = "output/"+BOOKID+".json";
		
		String basicWords = "";
		String translate = "https://www.googleapis.com/language/translate/v2?key=AIzaSyCK4nLnyGnoOG8jL815VmDjgjTc7nqXISM&q=%s&source=en&target=zh&callback=handleResponse";
		
		StringBuffer txt = new StringBuffer();

		// Words appear in the subtitle and its occurrence number.
		Hashtable<String, Integer> wordlist = new Hashtable<String, Integer>();
		try {
			// read basic word list
			basicWords = readBasicWords();
			
			// open json output
			BufferedWriter jsonfile = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outjson), "utf-8"));
			
			
			// open caption file
			BufferedReader rd = new BufferedReader(new InputStreamReader(new FileInputStream(subtitle), "utf-8"));
			String line = rd.readLine();
			while (line!=null) {
				txt.append(line+"\n");
				Pattern p = Pattern.compile("[a-zA-Z]{2,}");
				Matcher mb = p.matcher(line);
				while (mb.find()) {
					String word = mb.group().toLowerCase();			
					if (checkDupliate(word, basicWords)) {
						if (showRuleOut) {
							System.out.println("rule out a basic word: "+word);
						}
					} else {
						if (wordlist.get(word) != null) {
							wordlist.put(word, wordlist.get(word)+1);
						} else {
							wordlist.put(word, 1);
						}
					}
				}
				line = rd.readLine();
				//System.out.println(line);
			}
			rd.close();			
			
			// print out
			Vector sorted = new Vector(wordlist.keySet());
			Collections.sort(sorted);
			Enumeration<String> keys = sorted.elements();
			int totalWords = sorted.size();
			
			JSONHEAD = String.format(JSONHEAD, encodeUnicode(BOOKTITLE), BOOKURL, BOOKID, totalWords);
			jsonfile.append(JSONHEAD);
			
			String txtwhole = txt.toString().toLowerCase();
			int num = 0;			
			while(keys.hasMoreElements() && num<LIMIT) {
				String key = keys.nextElement();
				// translate it
				String strT;
				if (isTranslate) {
					URL url = new URL(String.format(translate, key));
					Object result = url.getContent();
					String json = null;
					if (result instanceof String) {
						json = (String)result;
					} else if (result instanceof InputStream) {
						BufferedReader resultreader = new BufferedReader(new InputStreamReader((InputStream) result, "utf8"));
						char buf[] = new char[1024];
						int size = resultreader.read(buf);
						while (size>0) {
							json += new String(buf);
							size = resultreader.read(buf);
						}
						resultreader.close();
					} else {
						System.out.println(result.getClass().getName());
					}	
					String tag = "\"translatedText\": \"";
					int tposb = json.indexOf(tag);
					int tpose = tposb;
					if (tposb>=0) {
						tposb = tposb+tag.length();
						tpose = json.indexOf("\"", tposb);
						strT = json.substring(tposb, tpose);
					} else {
						strT = "n/a";
					}
				} else {
					strT = "n/a";
				}
				// find context
				Pattern p = Pattern.compile("\\b"+key, Pattern.CASE_INSENSITIVE);				
				Matcher mb = p.matcher(txtwhole);	
				if (mb.find()) {
					int pos = mb.start();
					int bpos = pos;
					int epos = pos;
					if (pos-padding>=0) {
						bpos = pos - padding;
					} else {
						bpos = 0;
					}
					if (pos+padding<txtwhole.length()) {
						epos = pos + padding;
					} else {
						epos = txtwhole.length();
					}	
					String context = txt.toString().substring(bpos, pos)
						+" [ "+key+" ] "
						+txt.toString().substring(pos+key.length(),epos);
					
					System.out.println("["+num+":"+key+" "+wordlist.get(key)+"]");
					if (showContext) {
						System.out.println("context:"+context);
					}
					if (isSave) {
						saveEntry(BOOKID, num, key, wordlist.get(key), strT, context);
					}
					String jsonrow = "{\"book\":\"%s\", \"entry\":\"%s\", \"voice\":\"%d\", \"url\":\"%s\", \"shortdescription\":\"%s\", \"description\":\"%s\", \"timestamp\":\"\" }";
					if (num>0) {
						jsonfile.append(",");
					}
					jsonfile.append(String.format(jsonrow, BOOKID, key, wordlist.get(key), getEntryUrl(key), 
							encodeUnicode(strT), encodeUnicode(context)));
				} else {
					System.out.println(num+": "+key+" "+wordlist.get(key)+" "+strT+" ERROR: NOT FOUND MATCHES.");
				}
				num++;
			}
			jsonfile.append("]}");
			System.out.println("******Total Words/LIMIT:"+totalWords+"/"+LIMIT);
			jsonfile.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static String encodeUnicode(String str) {
		String rtn = "";
		for (int i=0; i<str.length(); i++) {
			rtn += String.format("\\u%04x", (int)str.charAt(i));
		}
		return rtn;
	}
	
	private static String readBasicWords() throws IOException {
		String rtn = "";
		for (int i=0; i<BASICLIST.length; i++) {
			BufferedReader rd = new BufferedReader(new FileReader(BASICLIST[i]));
			String line = rd.readLine().toLowerCase();
			while (line!=null) {
				rtn += line.toLowerCase()+" ";
				line = rd.readLine();
			}		
			rd.close();
		}
		return rtn;
	}
	
	private static boolean checkDupliate(String word, String dictionary) {
		if (ruleOutBasic) {
			if (word.endsWith("s")) {
				return dictionary.contains(word.substring(0, word.length()-1));
			} else if (word.endsWith("ed")) {
				return dictionary.contains(word.substring(0, word.length()-2));
			} else if (word.endsWith("ing")) {
				return dictionary.contains(word.substring(0, word.length()-3));
			} else {
				return dictionary.contains(word);
			}
		} else {
			return false;
		}
	}
	
	private static void saveEntry(String book, int num, String entry, Integer occur,
			String translate, String context) {
		if (!isTranslate ) {
			return;
		}
		try {
		    // Construct data
		    String data = URLEncoder.encode("book", "UTF-8") + "=" + URLEncoder.encode(book, "UTF-8");
		    data += "&" + URLEncoder.encode("entry", "UTF-8") + "=" + URLEncoder.encode(entry, "UTF-8");
		    data += "&" + URLEncoder.encode("voice", "UTF-8") + "=" + occur.toString();
		    data += "&" + URLEncoder.encode("url", "UTF-8") + "=" + getEntryUrl(entry);
		    data += "&" + URLEncoder.encode("shortdescription", "UTF-8") + "=" + URLEncoder.encode(translate, "UTF-8");		    
		    data += "&" + URLEncoder.encode("description", "UTF-8") + "=" + URLEncoder.encode(context, "UTF-8");		    

		    // Send data
		    URL url = new URL("http://vocabularystory.appspot.com/entry/create");
		    URLConnection conn = url.openConnection();
		    conn.setDoOutput(true);
		    OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
		    wr.write(data);
		    wr.flush();

		    // Get the response
		    BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
		    String result = "";
		    String line;
		    while ((line = rd.readLine()) != null) {
		    	result += line;
		    }
		    wr.close();
		    rd.close();
		    System.out.println(num+" "+entry+" "+result);
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}
}
